#include "mouse.h"

/**
 * 01.03.12 - Steven Hartin - Copied over from a previous project, added
 *                            comments and slighlty modified code to work with
 *                            this project.
 */

CMouse::CMouse() : CInputDevice(DEVICE_MOUSE) 
{
    /**
     * Constructor, ensure that the input device is intiailised with the 
     * DirectX device constant telling us which device this is representing.
     */
}

void CMouse::setUp(LPDIRECTINPUT8 pDirectInput, HWND hwndMain)
{
    /**
     * Sets up teh device and attempts to obtain the device lock.
     *
     * @param LPDIRECTINPUT8 The direct input device.
     * @param HWND hwndMain A handle to the window directx is running on.
     */
    if (FAILED(pDirectInput->CreateDevice(GUID_SysMouse, 
                                          getDevice(), 
                                          NULL)))
    {
        // The device cannot be created
        setActive(false);
        cleanUp();
    }
    else
    {
        if (FAILED((*getDevice())->SetDataFormat(&c_dfDIMouse2)))
        {
            // The format of the device cannot be assigned
            setActive(false);
            cleanUp();
        }
        else
        {
            // NOTE: To hide cursor, change NONEXCLUSIVE to EXCLUSIVE
            if (FAILED((*getDevice())->SetCooperativeLevel(hwndMain, 
                                        DISCL_FOREGROUND | DISCL_NONEXCLUSIVE)))
            {
                // We cannot obtain a lock on the mouse.
                setActive(false);
                cleanUp();
            }
            else
            {
                // Device successfully obtained and locked.
                setActive(true);
                (*getDevice())->Acquire();
            }
        }
    }
}

void CMouse::processState()
{
    /**
     * Processes the current state of the mouse. This requests the new device
     * state from direct input which populates the state. Call any callback
     * function associated with this.
     */
    if (! isActive())
    {
        return;
    }
    DIMOUSESTATE2 mouseState;
    HRESULT hr;

    // Clear the keyboard data buffer - just in case.
    ZeroMemory(&mouseState, sizeof(DIMOUSESTATE2));
    
    hr = (*getDevice())->GetDeviceState(sizeof(DIMOUSESTATE2),
                                         &mouseState); 
    if FAILED(hr) 
    { 
        // If this failed, the device has probably been lost.
        // Check for (hr == DIERR_INPUTLOST) and attempt to reacquire it here.

        setActive(false);

        hr = (*getDevice())->Acquire();
        while (hr == DIERR_INPUTLOST)
        {
            hr = (*getDevice())->Acquire();
        }

        hr = (*getDevice())->GetDeviceState(sizeof(DIMOUSESTATE2),
                                             &mouseState);
    } 

    if (!FAILED(hr))
    {
        // If we can find the keyboard device

        setActive(true);

        // Create the event
        DEVICE_EVENT deviceEvent;
        // Copy constructor
        deviceEvent.MouseState = mouseState;
        deviceEvent.type = getType();
        deviceEvent.pDevice = this;
        
        // Call all the registered event listeners
        processCallbacks(deviceEvent);
    }
}